//
//  EMImageViewer.m
//  EMImageView
//
//  Created by EasonWang on 13-12-9.
//  Copyright (c) 2013年 EasonWang. All rights reserved.
//

#define VERSION [[UIDevice currentDevice].systemVersion doubleValue]>=7

#import "EMImageViewer.h"

static const CGFloat kMinBlackMaskAlpha = 0.3f;
static const CGFloat kMaxImageScale = 2.5f;
static const CGFloat kMinImageScale = 1.0f;

@interface EMImageViewerCell : UITableViewCell
<
UIGestureRecognizerDelegate,
UIScrollViewDelegate
>
{
    UIImageView *_imageView;
    UIScrollView *_scrollView;
    NSMutableArray *_gestures;
    CGPoint _panOrigin;
    
    BOOL _isAnimating;
    BOOL _isDoneAnimating;
    BOOL _isLoaded;
}

@property (nonatomic,assign) CGRect originalFrameRelativeToScreen;
/** 根视图，作为最底层的图层支持 */
@property (nonatomic,weak) UIViewController *rootViewController;
@property (nonatomic,weak) UIViewController *viewController;
@property (nonatomic,weak) UIView *blackMask;
/** 传进来的 imageView */
@property (nonatomic,weak) UIImageView *senderView;
/** 默认图片，存放传进来的图片作为默首图片显示 */
@property (nonatomic,weak) UIImage *defaultImage;
/** 初始化的下标 */
@property (nonatomic,assign) NSInteger initialIndex;
/** 当前图片下标 */
@property (nonatomic,assign) NSInteger imageIndex;
@property (nonatomic,assign) UIButton *doneButton;

@property (nonatomic,weak) EMImageViewerOpeningBlock openingBlock;
@property (nonatomic,weak) EMImageViewerClosingBlock closingBlock;

@property (nonatomic,weak) UIView *superView;

/**用于浏览的所有图片视图*/
@property (nonatomic,weak) NSMutableArray *imageViewArray;

/**
 加载所有必要的视图
 */
- (void) loadAllRequiredViews;

/**
 设置图片在图片浏览器中显示，此方法可将需要显示的图片放入图片浏览器中进行包括缓动展开的效果
 @param imageURL 需要加载的图片的url，如果没有设置为nil
 @param defaultImage 默认显示出来的图片，及为第一个选中的显示图片
 @param imageIndex 图片浏览器中的当前图片的下标，用于进行左右滑动切换图片显示时的图片调用
 */
- (void) setImageURL:(NSURL *)imageURL defaultImage:(UIImage*)defaultImage imageIndex:(NSInteger)imageIndex;

/**
 加载数据源图片
 */
- (void) loadDatasourceImageViews:(UIImageView*)imageview;
@end

@implementation EMImageViewerCell
@synthesize blackMask = _blackMask;
@synthesize imageIndex = _imageIndex;
@synthesize initialIndex = _initialIndex;
@synthesize imageViewArray = _imageViewArray;


#pragma mark - 加载所有必须的视图文件
-(void)loadAllRequiredViews
{
    
    // 设置cell选中风格
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    // 获取屏幕尺寸
    CGRect frame = [[UIScreen mainScreen]bounds];
    // 初始化 _scrollView
    _scrollView = [[UIScrollView alloc]initWithFrame:frame];
    _scrollView.delegate = self;
    _scrollView.backgroundColor = [UIColor clearColor];
    [self addSubview:_scrollView];
    self.backgroundColor = [UIColor clearColor];
    // 添加结束button
    
}
#pragma mark - 设置图片文件，包括设置图片的手势监听、执行打开、滑动切换等

-(void)setImageURL:(NSURL *)imageURL defaultImage:(UIImage *)defaultImage imageIndex:(NSInteger)imageIndex
{
    _imageIndex = imageIndex;
    _defaultImage = defaultImage;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        _senderView.alpha = 0.0f;
        if (!_imageView) {  // 如果不存在imageview
            _imageView = [[UIImageView alloc]init];
            // 裁剪subviews局限于视图Bounds边界内，及根据imageview的实际大小显示image的区域范围
            _imageView.clipsToBounds = YES;
            [_scrollView addSubview:_imageView];
            _imageView.contentMode = UIViewContentModeScaleAspectFill;
        }
        
        // 使用 __block存储修饰符来声明局部变量，以对非局部变量做相应的修改操作
        __block UIImageView *_imageViewInTheBlock = _imageView;
        __block EMImageViewerCell *_justMeInsideTheBlock = self;
        __block UIScrollView *_scrollViewInsideBlock = _scrollView;
        
        // 设置imageview的图片
        [_imageView setImage:defaultImage];
        // 调整imageview的frame
        if (_imageIndex == _initialIndex && !_isLoaded) {
            _imageView.frame = _originalFrameRelativeToScreen;
            [UIView animateWithDuration:0.45f delay:0.0f options:0 animations:^{
                // 将 _imageView的图片调节到中间位置
                _imageView.frame =  [self centerFrameFromImage:_imageView.image];
                _imageView.contentScaleFactor = [UIScreen mainScreen].scale;
                // 恒等变换
                CGAffineTransform transform = CGAffineTransformIdentity;
                
                _rootViewController.view.transform = CGAffineTransformScale(transform, 0.95f, 0.95f);
                _viewController.view.transform = CGAffineTransformScale(transform, 1.05f, 1.05f);
                _blackMask.alpha = 1;
                
            } completion:^(BOOL finished){
                if (finished) {
                    _isAnimating = YES;
                    _isLoaded = YES;
                    if (_openingBlock) {
                        // 调用 openingBlock 函数
                        _openingBlock();
                    }
                }
            }];
        }else{
            [_scrollViewInsideBlock setZoomScale:1.0f animated:YES];
            [_imageViewInTheBlock setImage:_imageViewArray[_imageIndex]];
            _imageViewInTheBlock.frame = [_justMeInsideTheBlock centerFrameFromImage:_imageViewInTheBlock.image];
        }
        _imageView.userInteractionEnabled = YES;
        
        // 添加多种手势监听
        [self addMultipleGesture];
        
    });
}

-(void)loadDatasourceImageViews:(UIImageView *)imageview
{
    _imageView = imageview;
}

#pragma mark - 有关imageview坐标和大小的配置
- (CGRect) centerFrameFromImage:(UIImage*) image {
    if(!image) return CGRectZero;
    
    CGRect windowBounds = [UIScreen mainScreen].bounds;
    
    
    //    CGSize newImageSize = [self imageResizeBaseOnWidth:windowBounds.size.width oldWidth:image.size.width oldHeight:image.size.height];
    //    CGSize newImageSize = [self imageResizeBaseOnHeight:windowBounds.size.height oldWidth:image.size.width oldHeight:image.size.height];
    CGSize newImageSize = [self imageResizeBaseWithWindowBounds:windowBounds image:image];
    
    // 让尺寸充满设置的屏幕
    newImageSize.height = MIN(windowBounds.size.height,newImageSize.height);
    
    return CGRectMake(0.0f, windowBounds.size.height/2 - newImageSize.height/2, newImageSize.width, newImageSize.height);
}
// 根据图像的width计算
- (CGSize)imageResizeBaseOnWidth:(CGFloat) newWidth oldWidth:(CGFloat) oldWidth oldHeight:(CGFloat)oldHeight {
    // 调整大小比例
    CGFloat scaleFactor = newWidth / oldWidth;
    CGFloat newHeight = oldHeight * scaleFactor;
    return CGSizeMake(newWidth, newHeight);
}
// 根据图像的height计算
- (CGSize)imageResizeBaseOnHeight:(CGFloat) newHeight oldWidth:(CGFloat) oldWidth oldHeight:(CGFloat)oldHeight {
    // 调整大小比例
    CGFloat scaleFactor = newHeight / oldHeight;
    CGFloat newWidth = oldWidth * scaleFactor;
    return CGSizeMake(newWidth, newHeight);
}

- (CGSize)imageResizeBaseWithWindowBounds:(CGRect)windowBounds image:(UIImage *)image
{
    CGFloat width = 0.0f;
    CGFloat height = 0.0f;
    
    if (image.size.height/image.size.width > 1.75) {
        height = windowBounds.size.height;
        CGFloat scaleFactor = height/image.size.height;
        width = image.size.width * scaleFactor;
    }else{
        width = windowBounds.size.width;
        CGFloat scaleFactor = width/image.size.width;
        height = image.size.height * scaleFactor;
    }
    
    return CGSizeMake(width, height);
}

#pragma mark - 添加多种手势监听
-(void)addMultipleGesture
{
    // 双指点击
    UITapGestureRecognizer *twoFingerTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didTwoFingerTap:)];
    twoFingerTapGesture.numberOfTapsRequired = 1;
    twoFingerTapGesture.numberOfTouchesRequired = 2; // 触摸屏幕的手指数
    [_scrollView addGestureRecognizer:twoFingerTapGesture];
    
    // 单指点击
    UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didSingleTap:)];
    singleTapGesture.numberOfTapsRequired = 1;
    singleTapGesture.numberOfTouchesRequired = 1;   // 触摸屏幕的手指数
    [_scrollView addGestureRecognizer:singleTapGesture];
    
    // 双击
    UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didDoubleTap:)];
    doubleTapGesture.numberOfTapsRequired = 2;
    doubleTapGesture.numberOfTouchesRequired = 1;
    [_scrollView addGestureRecognizer:doubleTapGesture];
    
    // 创建手势之间依赖关系
    [singleTapGesture requireGestureRecognizerToFail:doubleTapGesture];
    // 设置scrollView的内容的最大和最小比例因子，内容将进行适度的大小缩放调整
    _scrollView.minimumZoomScale = kMinImageScale;
    _scrollView.maximumZoomScale = kMaxImageScale;
    
    _scrollView.zoomScale = 1.0;
    
    // 调整scrollView内容的中心点
    [self centerScrollViewContents];
}

#pragma mark - 手势监听的方法
// 双指点击
-(void)didTwoFingerTap:(UITapGestureRecognizer*)recognizer
{
    NSLog(@"双指点击");
}
// 单指点击
-(void)didSingleTap:(UITapGestureRecognizer*)recognizer
{
    [self dismissViewController];
    NSLog(@"单指点击");
}
// 双击
-(void)didDoubleTap:(UITapGestureRecognizer*)recogizer
{
    NSLog(@"双击");
}

#pragma mark - 调整scrollView内容的中心，是内容保持在中心显示
-(void)centerScrollViewContents
{
    // 获取根视图的bounds的size
    CGSize boundsSize = [UIScreen mainScreen].bounds.size;
    // 获取scrollView的内容的frame
    CGRect contentsFrame = _imageView.frame;
    
    // 进行中心点调整
    if (contentsFrame.size.width < boundsSize.width) {
        contentsFrame.origin.x = (boundsSize.width-contentsFrame.size.width)/2.0f;
    }else{
        contentsFrame.origin.x = 0;
    }
    
    if (contentsFrame.size.height < boundsSize.height) {
        contentsFrame.origin.y = (boundsSize.height-contentsFrame.size.height)/2.0f;
    }else{
        contentsFrame.origin.y = 0;
    }
    
    _imageView.frame = contentsFrame;
}

#pragma mark - 设置图片浏览器动画消失效果
/** 退出图片视图浏览器，并将imageview复原到先前查看的状态 */
-(void)dismissViewController
{
    dispatch_async(dispatch_get_main_queue(), ^{
        
        //        CGFloat screenHeight = _rootViewController.view.frame.size.height;
        //        CGFloat imageYPosition = _imageView.frame.origin.y;
        //
        //        BOOL isGoingUp = ! imageYPosition > screenHeight/2;
        
        [UIView animateWithDuration:0.45f delay:0.0f options:0 animations:^{
            if (_imageIndex == _initialIndex) {
                // 设置 _imageView的框架为相对于屏幕坐标系的最原始的值
                _imageView.frame = _originalFrameRelativeToScreen;
            }else{
                // 缓慢方大并逐渐消失
                float x = 2.0f;
                float y = 2.0f;
                _imageView.transform = CGAffineTransformMakeScale(x, y);
                _imageView.alpha = 0.1f;
                _senderView.alpha = 1.0f;
            }
            
            // 恒等变换
            CGAffineTransform trans = CGAffineTransformIdentity;
            _rootViewController.view.transform = CGAffineTransformScale(trans, 1.0f, 1.0f);
            _viewController.view.transform = CGAffineTransformScale(trans, 1.0f, 1.0f);
            
            _blackMask.alpha = 0.0f;
            
        } completion:^(BOOL finished){
            if (finished) {
                // 移除view
                [_viewController.view removeFromSuperview];
                // 从父VC中移除，及从根视图中移动此VC
                [_viewController removeFromParentViewController];
                
                _senderView.alpha = 1.0f;
                // 显示状态栏
                [UIApplication sharedApplication].statusBarHidden = NO;
                _isAnimating = NO;
                if (_closingBlock) {
                    _closingBlock();
                }
            }
        }];
    });
}

@end





@interface EMImageViewer ()
<
UIGestureRecognizerDelegate,
UIScrollViewDelegate,
UITableViewDataSource,
UITableViewDelegate
>
{
    UIWindow *_overlayWindow;
    UITableView *_tableView;
    NSMutableArray *_gestures;
    UIView *_blackMask;
    UIImageView *_imageView;
    UIView *_superView;
    
    CGPoint _panOrigin;
    /** 相对于屏幕坐标系而言的图片的起始位置(origin)所在位置，以屏幕左上角为坐标系原点（0，0)，同时为当前图片视图的原始位置 */
    CGRect _originalFrameRelativeToScreen;
    
    BOOL _isAnimating;
    BOOL _isDoneAnimating;
}
@end

@implementation EMImageViewer
@synthesize rootViewController = _rootViewController;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 隐藏状态栏
    [UIApplication sharedApplication].statusBarHidden = YES;
    // 获取根视图的bounds
    CGRect windowBounds = [[UIScreen mainScreen]bounds];
    /** 得到所设定的imageview在屏幕坐标系中的坐标，此方法从接收机 _senderView(UIImageView)的坐标系的矩形到主屏幕视图中的转换 */
    CGRect newFrame = [_senderView convertRect:[[UIScreen mainScreen]applicationFrame] toView:nil];
    
    float originY = newFrame.origin.y;
    // 如果为iOS7操作系统，调整原点y轴上移40像素，解决图片浏览器显示图片出现卡顿现象，优化图片显示更平滑的效果
    if (VERSION) {
        originY -= 20;
    }
    newFrame.origin = CGPointMake(newFrame.origin.x, originY);
    newFrame.size = _senderView.frame.size;
    _originalFrameRelativeToScreen = newFrame;
    self.view = [[UIView alloc]initWithFrame:windowBounds];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    
    // 添加 Tableview
    _tableView = [[UITableView alloc]initWithFrame:windowBounds style:UITableViewStylePlain];
    
    [self.view addSubview:_tableView];
    // 旋转 -90度
    _tableView.transform = CGAffineTransformMakeRotation(-M_PI_2);
    
    _tableView.frame = CGRectMake(0,(VERSION?0:-20), windowBounds.size.width, windowBounds.size.height);
    
    // 分页滚动视图
    _tableView.pagingEnabled = YES;
    // 数据源和代理
    _tableView.dataSource = self;
    _tableView.delegate = self;
    // 设置 table cells 之间的分隔符
    _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    // backgroundColor
    _tableView.backgroundColor = [UIColor clearColor];
    // 设置垂直滚动指示不可见
    _tableView.showsVerticalScrollIndicator = NO;
    [_tableView setContentOffset:CGPointMake(0, self.initialIndex*_rootViewController.view.frame.size.width)];
    NSLog(@"%f",_initialIndex * _rootViewController.view.frame.size.width);
    _blackMask = [[UIView alloc]initWithFrame:CGRectMake(windowBounds.origin.x, (VERSION?0:-20), windowBounds.size.width, windowBounds.size.height+20)];
    _blackMask.backgroundColor = [UIColor blackColor];
    _blackMask.alpha = 0.0f;
    // 自动调整视图的宽高
    _blackMask.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    [self.view insertSubview:_blackMask atIndex:0];
}

#pragma mark - Tableview datasource

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // 如果不存在数据源则返回1
    if(!self.imageDatasource) return 1;
    // 返回数据源图片个数
    return [self.imageDatasource numberImagesFromImageViewer:self];
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return _rootViewController.view.frame.size.width;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * cellID = @"EMImageViewerCell";
    
    // 自定义的cell
    EMImageViewerCell * imageViewerCell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(!imageViewerCell) {
        CGRect windowFrame = [UIScreen mainScreen].applicationFrame;
        imageViewerCell = [[EMImageViewerCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
        imageViewerCell.transform = CGAffineTransformMakeRotation(M_PI_2);
        imageViewerCell.frame = CGRectMake(0,0,windowFrame.size.width, windowFrame.size.height);
        imageViewerCell.originalFrameRelativeToScreen = _originalFrameRelativeToScreen;
        imageViewerCell.viewController = self;
        imageViewerCell.blackMask = _blackMask;
        imageViewerCell.rootViewController = _rootViewController;
        imageViewerCell.openingBlock = _openingBlock;
        imageViewerCell.closingBlock = _closingBlock;
        imageViewerCell.superView = _senderView.superview;
        imageViewerCell.senderView = _senderView;
        imageViewerCell.initialIndex = _initialIndex;
        imageViewerCell.imageViewArray = [self.imageDatasource getImageViewArray];
        [imageViewerCell loadAllRequiredViews];
    }
    
    if (!self.imageDatasource) {
        
    }else{
        [imageViewerCell setImageURL:nil defaultImage:_senderView.image imageIndex:indexPath.row];
        //     [imageViewerCell setImageURL:nil defaultImage:[self.imageDatasource getImageFromDatasource:nil] imageIndex:indexPath.row];
    }
    return imageViewerCell;
}



- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)presentImageViewer
{
    
    //        [self createOverlayWindow];
    
    // 获取根控制器
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    [self presentFromViewController:rootViewController];
}
- (void)presentFromViewController:(UIViewController *)controller
{
    _rootViewController = controller;
    // 将当前控制器作为子控制器加入到根控制器中
    [controller addChildViewController:self];
    [controller.view addSubview:self.view];// self.view
    [self didMoveToParentViewController:controller];
}

// create overlayWindow
- (void)createOverlayWindow
{
	_overlayWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
	_overlayWindow.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	_overlayWindow.backgroundColor = [UIColor clearColor];
	[_overlayWindow makeKeyAndVisible];
	[_overlayWindow addSubview:self.view];
}

@end

#pragma mark - Custom Gesture Recognizer that will Handle imageView

@interface EMImageViewerGestureRecognizer : UITapGestureRecognizer

/** openingBlock */
@property (nonatomic, strong) EMImageViewerOpeningBlock openingBlock;
/** closingBlock */
@property (nonatomic, strong) EMImageViewerClosingBlock closingBlock;
/** 初始下标 */
@property (nonatomic, assign) NSInteger initialIndex;
/** 图片数据源(及代理delegate)*/
@property (nonatomic, weak) id<EMImageViewerDelegate> imageDatasource;

@end


@implementation EMImageViewerGestureRecognizer

@synthesize openingBlock;
@synthesize closingBlock;
@synthesize initialIndex;
@synthesize imageDatasource;

@end


#pragma mark - UIImageView Category

@implementation UIImageView (EMImageViewer)

/**
 对imageview添加手势监听，此方法为UIImageView的扩展方法，可对imageview进行点击监听，并进行相对应的响应
 @param imageDatasource 图片数据源的代理(delegate)，需先实现EMImageViewerDelegate委托
 @param initialIndex 初始化下标，及为即将在图片浏览器中显示的图片的下标
 @param open EMImageViewerOpeningBlock的对象，图片浏览器启动后将执行此block，可以在此block中对浏览器打开后的操作
 @param close EMImageViewerClosingBlock对象，图片浏览器退出后将执行此block，可以在此block中对图片浏览器退出后的操作
 */
- (void)setupImageViewerWithDataSource:(id<EMImageViewerDelegate>)imageDatasource initialIndex:(NSInteger)initialIndex onOpen:(EMImageViewerOpeningBlock)open onClose:(EMImageViewerClosingBlock)close
{
    
    self.contentMode = UIViewContentModeScaleAspectFill;
    
    // 裁剪subviews局限于视图Bounds边界内，及根据imageview的实际大小显示image的区域范围
    self.clipsToBounds = YES;
    
    self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    
    // 注：需要设置 userInteractionEnabled 为 yes，否则不响应触摸事件
    [self setUserInteractionEnabled:YES];
    // 添加tap手势对imageView进行操作
    EMImageViewerGestureRecognizer *recognizer = [[EMImageViewerGestureRecognizer alloc]initWithTarget:self action:@selector(didTap:)];
    recognizer.openingBlock = open;
    recognizer.closingBlock = close;
    recognizer.initialIndex = initialIndex;
    recognizer.imageDatasource = imageDatasource;
    [self addGestureRecognizer:recognizer];
    recognizer = nil;
}

-(void)didTap:(EMImageViewerGestureRecognizer*)recognizer
{
    EMImageViewer *imageBrower = [[EMImageViewer alloc]init];
    imageBrower.senderView = self;
    imageBrower.initialIndex = recognizer.initialIndex;
    imageBrower.openingBlock = recognizer.openingBlock;
    imageBrower.closingBlock = recognizer.closingBlock;
    imageBrower.imageDatasource = recognizer.imageDatasource;
    if (self.image) {
        [imageBrower presentImageViewer];
    }
}




@end





